package MAgentAssignment;

import MAgentAssignment.gui.InterfaceAgent;
import MAgentAssignment.ontology.FlightOntology;
import MAgentAssignment.ontology.FlightVocabulary;
import MAgentAssignment.ontology.actions.CreateAirpot;
import MAgentAssignment.ontology.actions.CreateNewFlight;
import MAgentAssignment.ontology.actions.Land;
import MAgentAssignment.ontology.concepts.Flight;
import jade.content.lang.Codec;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.FIPAException;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import jade.wrapper.AgentContainer;

import java.io.IOException;

/**
 * Created by IntelliJ IDEA.
 * User: prageeth
 * Date: 2/16/12
 * Time: 2:25 PM
 * To change this template use File | Settings | File Templates.
 */
public class FlightAgent extends Agent
{
    private Codec codec = new SLCodec();
    private Ontology ontology = FlightOntology.getInstance();
    private Flight flight;

    @Override protected void setup()
    {
        getContentManager().registerLanguage( codec );
        getContentManager().registerOntology( ontology );

        ServiceDescription sd = new ServiceDescription();
        sd.setType( "FLIGHT" );
        sd.setName( getLocalName() );
        DFAgentDescription dfd = new DFAgentDescription();
        dfd.setName( getAID() );
        dfd.addServices( sd );
        try
        {
            DFService.register( this, dfd );
        }
        catch( FIPAException fe )
        {
            fe.printStackTrace();
        }

        addBehaviour( new CyclicBehaviour()
        {
            @Override public void action()
            {
                // inform the pilot agent when the time comes to take off
                // flightAgent and the pilot agent work together for a common goal
                // when taking off inform the airports from and to

                ACLMessage msg = receive( MessageTemplate.MatchPerformative( ACLMessage.INFORM ) );

                if( msg != null )
                {
                    if( msg.getContent() != null )
                    {
                        if( msg.getContent().equals( FlightVocabulary.FLIGHT_CANCELLED ) )
                        {
                            block();
                        }
                        else if( flight != null && msg.getContent().toString().contains( flight.getFlightNo() ) )
                        {
                            System.out.println( getName() + "Arrived" );
                            flight.setLanded( true );
                            //                            return;
                        }
                    }

                    Object contentObj = null;
                    try
                    {
                        contentObj = msg.getContentObject();
                    }
                    catch( UnreadableException e )
                    {
                        e.printStackTrace();
                    }
                    if( contentObj != null )
                    {
                        if( contentObj instanceof CreateNewFlight )
                        {
                            CreateNewFlight createNewFlight = (CreateNewFlight) contentObj;
                            flight = createNewFlight.getFlight();
                            addBehaviour( new OneShotBehaviour()
                            {
                                @Override public void action()
                                {
                                    ACLMessage msg = new ACLMessage( ACLMessage.INFORM );
                                    msg.setLanguage( codec.getName() );
                                    try
                                    {
                                        CreateNewFlight createNewFlight = new CreateNewFlight();
                                        createNewFlight.setFlight( flight );
                                        msg.setContentObject( createNewFlight );
                                    }
                                    catch( IOException e )
                                    {
                                        e.printStackTrace();
                                    }

                                    msg.addReceiver( new AID( InterfaceAgent.agentName, AID.ISLOCALNAME ) );
                                    DFAgentDescription airpotTemplate = new DFAgentDescription();
                                    ServiceDescription sd = new ServiceDescription();
                                    sd.setType( "AIRPORT" );
                                    airpotTemplate.addServices( sd );

                                    DFAgentDescription[] result = new DFAgentDescription[0];
                                    try
                                    {
                                        result = DFService.search( myAgent, airpotTemplate );
                                    }
                                    catch( FIPAException e )
                                    {
                                        e.printStackTrace();
                                    }
                                    for( DFAgentDescription dfAgentDescription : result )
                                    {
                                        msg.addReceiver( new AID( dfAgentDescription.getName().getLocalName(), AID.ISLOCALNAME ) );
                                    }
                                    send( msg );
                                }
                            } );
                        }
                        else if( contentObj instanceof Land )
                        {
                            informFlightArrival( flight );
                            System.out.println( "Informing" + flight.getFlightNo() );
                        }
                    }
                }

                if( flight != null && flight.isLanded() )
                {
                    informFlightArrival( flight );
                    System.out.println( "Informing" + flight.getFlightNo() );
                    block();
                }

            }
        } );


        //        addBehaviour( new TickerBehaviour( this, 300 )
        //        {
        //            @Override protected void onTick()
        //            {
        //                if( flight.isLanded() )
        //                {
        //                    addBehaviour( new OneShotBehaviour()
        //                    {
        //                        @Override public void action()
        //                        {
        //                            informFlightArrival( flight );
        //                            doDelete();
        //                        }
        //                    } );
        //                    stop();
        //                }
        //            }
        //        } );

    }

    public void informFlightArrival( Flight flight )
    {
        DFAgentDescription template = new DFAgentDescription();
        ServiceDescription sd = new ServiceDescription();
        sd.setType( "AIRLINE" );
        template.addServices( sd );
        DFAgentDescription airpotTemplate = new DFAgentDescription();
        sd = new ServiceDescription();
        sd.setType( "AIRPORT" );
        airpotTemplate.addServices( sd );
        try
        {
            ACLMessage msg = new ACLMessage( ACLMessage.INFORM );
            msg.setContent( flight.getFlightNo() );
            DFAgentDescription[] result = DFService.search( this, template );
            for( DFAgentDescription dfAgentDescription : result )
            {
                msg.addReceiver( new AID( dfAgentDescription.getName().getLocalName(), AID.ISLOCALNAME ) );
            }
            send( msg );

            msg = new ACLMessage( ACLMessage.INFORM );
            try
            {
                msg.setContentObject( flight );
            }
            catch( IOException e )
            {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
            result = DFService.search( this, airpotTemplate );
            for( DFAgentDescription dfAgentDescription : result )
            {
                msg.addReceiver( new AID( dfAgentDescription.getName().getLocalName(), AID.ISLOCALNAME ) );
            }
            send( msg );
        }
        //        catch( IOException e )
        //        {
        //            e.printStackTrace();
        //        }
        catch( FIPAException fe )
        {
            fe.printStackTrace();
        }
        doDelete();

    }
}
